package m.toolkit.console;

import java.io.BufferedReader;
import java.io.InputStreamReader;

import m.Config;
import m.framework.exception.SystemException;
import m.framework.utils.StrBuilder;
import m.framework.utils.StringUtil;
import m.toolkit.console.Command.Status;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 命令执行者
 * @author ming
 * @date 2014年2月22日下午10:24:10
 */
public class CommandExecutor implements Runnable{
	
	private static Logger log = LoggerFactory.getLogger(CommandExecutor.class);
	private Command command;
	private StrBuilder sb=new StrBuilder();
	public CommandExecutor(Command command){
		if(StringUtil.isEmpty(command.getCharsetName())){
			command.setCharsetName(Config.OS_CHARSET_NAME);
		}
		if(command.getOutSize()==null){
			command.setOutSize(CommandConfig.getOutputSize());
		}
		if(command.getOutSpilt()==null){
			command.setOutSpilt(CommandConfig.getOutputTimeSplit());
		}
		
		command.setOutputHolder(new OutputHolder(command.getOutSize()));
		
		command.updateStatus(null,Status.未知);
		this.command=command;
	}
	
	
	
	public void run() {
		try {
			runImpl();
		} catch (Exception e) {
			log.error("执行命令行出错:"+command.getCommandContent()+"\n"+e.getMessage(),e);
			command.updateStatus(null,Status.失败);
			command.setEndTime(System.currentTimeMillis());
			command.setException(e);
		}
		
	}
	
	private void runImpl() throws Exception{
		command.setBeginTime(System.currentTimeMillis());
		if(command.getStatus()==Status.未知){
			command.updateStatus(Status.未知, Status.执行中);
		}else{
			return;
		}
		new OutputMover().start();
		
		Process p= Runtime.getRuntime().exec(command.getCommandContent());
		BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream(),command.getCharsetName()));  
        String line = "";  
        while ((line = input.readLine()) != null) {
            if(command.getStatus()!=Status.执行中){
            	return;
            }
            sb.appendLine(line);
        }
        command.setEndTime(System.currentTimeMillis());
        command.updateStatus(null,Status.成功);
	}

	//定时保存执行结果
	private class OutputMover extends Thread{
		public OutputMover(){
			super("outputMover");
		}
		public void run(){
			try {
				//假定大部分命令都能在500ms内完成,所以上来先睡一秒以便一次性读取全部日志
				Thread.sleep(500);
			} catch (InterruptedException e) {
				log.error("保存命令行日志时出错");
				throw new SystemException("保存命令行日志时出错",e);
			}
			while(true){
				command.getOutputHolder().add(sb.toString(),System.currentTimeMillis());
				sb=new StrBuilder();
				if(command.getStatus()!=Status.执行中){
					break;
				}
				try {
					Thread.sleep(command.getOutSpilt()*1000);
				} catch (InterruptedException e) {
					log.error("保存命令行日志时出错");
					throw new SystemException("保存命令行日志时出错",e);
				}
			}
		}
	}


	//任务取消,线程池满的时候调用
	public void cancel() {
		long time=System.currentTimeMillis();
		command.setBeginTime(time);
		command.setEndTime(time);
		command.updateStatus(null,Status.取消);
	}
	
	
	public String getOut(){
		return sb.toString();
	}
	
	public Command getCommand(){
		return command;
	}

	//手动调用
	public void stop() {
		long time=System.currentTimeMillis();
		command.setEndTime(time);
		command.updateStatus(null,Status.中止);
	}
}




